#include "htmlsyntaxhighlighter.h"

HtmlSyntaxHighlighter::HtmlSyntaxHighlighter(QObject *parent) :
    QSyntaxHighlighter(parent)
{
    formats_[Element].setForeground(Qt::darkRed);
    formats_[Element].setFontWeight(QFont::Bold);
    formats_[Element].setFontStyleStrategy(QFont::PreferAntialias);

    formats_[Comment].setForeground(Qt::gray);

    formats_[Quote].setForeground(Qt::darkBlue);

    formats_[Entity].setForeground(Qt::darkGreen);

    formats_[Attribute].setForeground(QColor(Qt::darkGreen).darker(150));

    formats_[Generic].setForeground(QBrush(QColor(200,73,0)));
}

void HtmlSyntaxHighlighter::highlightBlock(const QString &text)
{
    int state = previousBlockState();
    int len = text.length();
    int start = 0;
    int end = -1;
    int pos = 0;

    while(pos < len) {
        switch(state) {
        case NormalState:
        default:
            while(pos < len) {
                QChar c = text.at(pos);
                if(c == '<') {
                    if(text.mid(pos, 4) == "<!--")
                        state = InComment;
                    else
                        state = InElement;
                    break;
                }
                else if(c == '&') {
                    start = pos;
                    while(pos < len && text.at(pos++) != ';');
                    setFormat(start, pos - start, formats_[Entity]);
                } else
                    pos++;
            }
            break;
        case InComment:
            start = pos;
            while(pos < len) {
                if(text.mid(pos, 3) == "-->") {
                    pos += 3;
                    state = NormalState;
                    break;
                } else
                    pos++;
            }
            setFormat(start, pos - start, formats_[Comment]);
            break;
        case InElement:
            start = pos++;
            if(text.at(pos) == '/')
                pos++;
            setFormat(start, pos - start, formats_[Generic]);
            start = pos;
            while(pos < len && text.at(pos) == ' ')
                pos++;
            while(pos < len && text.at(pos) != ' ' && text.at(pos) != '>')
                pos++;
            while(pos < len && text.at(pos) == ' ')
                pos++;
            setFormat(start, pos - start, formats_[Element]);
            if(pos < len) {
                if(text.at(pos) == '>') {
                    setFormat(pos++, 1, formats_[Generic]);
                    state = NormalState;
                }
                else {
                    state = InAttributeList;
                }
            }
            break;
        case InQuote:
            start = pos;
            pos++;
            while(pos < len) {
                if(text.at(pos) == '"') {
                    pos++;
                    state = InAttributeList;
                    break;
                }
                else
                    pos++;
            }
            setFormat(start, pos - start, formats_[Quote]);
            break;
        case InAttributeList:
            start = pos;
            while(pos < len) {
                if(text.at(pos) == '"') {
                    state = InQuote;
                    break;
                }
                else if(text.at(pos) == '>') {
                    end = pos++;
                    state = NormalState;
                    break;
                }
                else
                    pos++;
            }
            setFormat(start, pos - start, formats_[Attribute]);
            setFormat(end, 1, formats_[Generic]);
            break;
        }
    }

    setCurrentBlockState(state);
}
